/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.dpy.appmvdpy.Controllers;

import com.dpy.appmvdpy.Facades.DefaultFacade;
import com.dpy.appmvdpy.Models.DefaultModel;
import com.dpy.appmvdpy.Models.Exporters.Exporter;
import com.dpy.appmvdpy.Models.Importers.Importer;
import com.dpy.appmvdpy.Models.Validators.DefaultValidator;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.util.FileCopyUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.ModelAndView;

/**
 *
 * @author Lilli
 */

public abstract class DefaultController<T> {
    
    private Class<? extends DefaultModel> entityClass;
    protected String controllerName;
    
    public DefaultController(Class<? extends DefaultModel> entityClass, String controllerName)
    {
          this.entityClass = entityClass;         
          this.controllerName = controllerName;
    }
    
    
    @RequestMapping("/list")
    public ModelAndView list(@RequestParam(required= false, defaultValue="0") int pag)
    {
        ModelAndView model = new ModelAndView("/" + controllerName + "/list");
        System.out.println(getFacade());
        List<T> listModel = getFacade().listAll(pag);
        model.addObject("listModel",listModel);
        model.addObject("pageNumbers",getFacade().pageNumbers());
        
        return model;
    }
    
    @RequestMapping(value="/add", method=RequestMethod.GET)
    public ModelAndView create()
    {
	  ModelAndView model = new ModelAndView("/" + controllerName + "/add");
	  T entity = createObject();
	  model.getModelMap().put("model", entity);
	  return model;
    }
    
    
    public ModelAndView create(T model)
    {
       ModelAndView m = this.create();
       m.getModelMap().remove("model");
       m.addObject("model",model);
       return m;
    }
    
         @RequestMapping(value="/save", method=RequestMethod.POST)
	 public ModelAndView create(@ModelAttribute("model")T model, BindingResult result, SessionStatus status)
	 {
	  getValidator().validate(model, result);
	  if (result.hasErrors())
	  {  
	     return this.create(model);
	  }
          
          DefaultModel instanced = (DefaultModel)model;
	  
          if (instanced.getId() == null || instanced.getId() == 0)
              getFacade().add(model);
          else 
              getFacade().edit(model);
          
	  status.setComplete();
	  return this.list(0);
	 }
         
         @RequestMapping(value="/search", method=RequestMethod.POST)
         public ModelAndView search(@RequestParam(required=true)String name)
         {
             return new ModelAndView("/" + controllerName + "/list", "listModel",getFacade().searchByName(name));         
         }
         
         @RequestMapping(value="/edit",method=RequestMethod.GET)
         public ModelAndView edit(@RequestParam(required=true)int id)
         {
             T entity = getFacade().getById(id);
             ModelAndView model = new ModelAndView("/" + controllerName + "/add");
             model.getModelMap().put("model", entity);
             return model;                  
         }
         
          @RequestMapping(value="/delete",method=RequestMethod.GET)
         public ModelAndView delete(@RequestParam(required=true)int id)
         {
             getFacade().delete(id);
             ModelAndView model = new ModelAndView("/" + controllerName + "/list");
             model.addObject("listModel",getFacade().listAll(0));
             return model;                  
         }   
          
         @RequestMapping(value="/detail",method=RequestMethod.GET)
         public ModelAndView detail(@RequestParam(required=true)int id)
         {             
             ModelAndView model = new ModelAndView("/" + controllerName + "/detail");
             model.addObject("model",getFacade().getById(id));
             return model;                  
         }        
       
         @RequestMapping(value="/print",method=RequestMethod.GET)
         public ModelAndView print(@RequestParam(required=true)int id)
         {             
             ModelAndView model = new ModelAndView("/" + controllerName + "/print");
             model.addObject("model",getFacade().getById(id));
             return model;                  
         }   
         

         
         
       @RequestMapping("/export")
       public ModelAndView download(HttpServletRequest request,
        HttpServletResponse response) throws Exception {
        int id = ServletRequestUtils.getRequiredIntParameter(request, "id");
        
        List<T> list = new ArrayList<T>();
        list.add(getFacade().getById(id));
        File file = getExporter().doExport(list);

        response.setContentType("text/txt");
        response.setHeader("Content-Disposition","attachment; filename=\"" + file.getName() +"\"");

        FileCopyUtils.copy(new FileInputStream(file), response.getOutputStream());

        return null;

    }
         
    
         
    public abstract DefaultFacade<T> getFacade();   
    public abstract T createObject();
    public abstract DefaultValidator<T> getValidator();
   
    public Exporter<T> getExporter()
    {
      return null;
    }
    
    public Importer<T> getImporter(File file)
    {
      return null;
    }
    
    @RequestMapping("/import")
    public ModelAndView Import()
    {
       return new ModelAndView("/" + controllerName + "/import");
    }
    
    @RequestMapping(value="/import", method= RequestMethod.POST)
    public ModelAndView upload(HttpServletRequest request,
        HttpServletResponse response) throws Exception {
        
       InputStream i = request.getPart("file").getInputStream();
       File f = new File("fdcli.txt");
       OutputStream stream = new FileOutputStream(f);
       byte[] buf = new byte[1024];
       int len = 0;
       
       while((len=i.read(buf)) > 0)
       {
           stream.write(buf);
           buf = new byte[1024];
       }
       stream.close();
       i.close();
        
        for(T entity: getImporter(f).doImport())
        {       
             getFacade().edit(entity);
        }
          
        return this.list(0);
    }
    
}
